package com.jsbb.common.aspect;

import com.alibaba.fastjson.JSON;
import com.jsbb.mapper.log.LogApiMapper;
import com.jsbb.entity.log.LogApi;
import com.jsbb.util.IdUtils;
import com.jsbb.util.LoggerUtils;
import com.jsbb.util.RequestUtils;
import com.jsbb.util.TokenUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;

/**
 * 接口日志切面
 *
 * @author jsbb
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogApiMapper logApiMapper;

    @Pointcut("execution(public * com.jsbb.controller..*.*(..))")
    public void pointcut() {
    }

    /**
     * 环绕通知
     *
     * @param point
     * @return
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Object result = null;
        try {
            result = point.proceed();
        } catch (Throwable throwable) {
            long time = System.currentTimeMillis() - beginTime;
            if (throwable.getMessage() != null) {
                String[] arr = throwable.getMessage().split("\r\n");
                String err;
                if (arr.length > 1) {
                    err = arr[1];
                } else {
                    err = arr[0];
                }
                addLog(point, time, err);
            }
            throw throwable;
        }
        long time = System.currentTimeMillis() - beginTime;
        addLog(point, time, null);
        return result;
    }

    private void addLog(ProceedingJoinPoint joinPoint, long time, String err) {
        try {
            HttpServletRequest request = RequestUtils.getRequest();
            String uri = request.getRequestURI();
            if (uri.equals("/") || uri.endsWith("/index")) {
                return;
            }
            LogApi logApi = new LogApi();
            logApi.setId(IdUtils.getLongId());
            logApi.setUserId(TokenUtils.getUserId(request));
            logApi.setUrl(request.getRequestURI());
            logApi.setTime((int) time);
            logApi.setIp(RequestUtils.getIpAddress(request));
            logApi.setParam(getParam(joinPoint));
            logApi.setErr(err);
            logApi.setCreateTime(LocalDateTime.now());
            logApi.setUpdateTime(logApi.getCreateTime());
            logApiMapper.insert(logApi);
        } catch (Exception e) {
            LoggerUtils.error("记录接口日志异常={}", e.getMessage());
        }
    }

    private String getParam(ProceedingJoinPoint point) {
        if (!ObjectUtils.isEmpty(point.getArgs())) {
            for (Object object : point.getArgs()) {
                if (!(object instanceof HttpServletRequest) && !(object instanceof HttpServletResponse) && !(object instanceof MultipartFile)) {
                    String param = JSON.toJSONString(object);
                    return param.length() >= 20000 ? param.substring(0, 20000 - 1) : param;
                }
            }
        }
        return null;
    }
}
